#ifndef CPU_H
#define CPU_H

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#define	A	0
#define	B	1
#define C	2
#define D	3
#define	E	4
#define	H	5
#define	L	6
#define F	7
#define M	8
#define	PC	0
#define	SP	1

#define	BC	3
#define	DE	4
#define	HL	5

typedef	unsigned char	byte;
typedef	unsigned short	word;

word time;

byte regs8[9];
word regs16[2];

void dispatch(byte op);
void reset();

///////////
//Opcodes//
///////////

//Load Reg <-> Reg
void LD_reg_reg(byte reg1, byte reg2);

//Load (HL) <-> Reg
void LD_HLm_reg(byte reg);
void LD_reg_HLm(byte reg);

//Load A <-> Mem
void LD_A_reg16m(byte reg16m);
void LD_A_mem(word adr);
void LD_reg16m_A(byte reg16m);
void LD_mem_A(word adr);

//Load 16-bit -> Reg
void LD_reg16_lit(byte reg16);

//Load 8-bit -> Mem/Reg
void LD_reg_lit(byte reg);
void LD_HLm_lit();

//Put Stack Pointer in memory
void LD_nnmSP(word adr);
//Put HL in Stack Pointer
void LD_SPHL();
//Add signed literal to SP and put in HL
void LDHL_SP_d(signed char value);

//LDH
void LDH_nmA(byte value);
void LDH_Anm(byte value);
void LDH_CmA(byte value);

/////////////////////
//Jumpstyle time???//
/////////////////////

void JRn(byte rel_adr);
void JRZn(byte rel_adr);
void JRNZn(byte rel_adr);
void JRCn(byte rel_adr);
void JRNCn(byte rel_adr);

void JPnn(word adr);
void JPZnn(word adr);
void JPNZnn(word adr);
void JPCnn(word adr);
void JPNCnn(word adr);

void JP_HLm();

//Increments
void INC_reg(byte reg);
void INC_HLm();

//Decrements
void DEC_reg(byte reg);
void DEC_HLm();

//Set & clear Carry
void SCF();
void CCF();

//////////////
//Arithmetic//
//////////////

//Rotations
void RLA();
void RRA();
void RLCA();
void RRCA();
//Complement
void CPL();
//Decimal addition
void DAA();
//Add
void ADD_A_reg(byte reg);
void ADD_A_HLm();
void ADD_A_lit(byte value);
void ADD_SP_D(signed char value);
//16-bit Add
void ADD_HLBC();
void ADD_HLDE();
void ADD_HLHL();
void ADD_HLSP();
//Add with carry
void ADC_reg(byte reg);
void ADC_HLm();
void ADC_lit(byte value);
//Sub
void SUB_reg(byte reg);
void SUB_HLm();
void SUB_lit(byte value);
//Sub with carry
void SBC_reg(byte reg);
void SBC_HLm();
void SBC_lit(byte value);
//And
void AND_reg(byte reg);
void AND_HLm();
void AND_lit(byte value);
//Xor
void XOR_reg(byte reg);
void XOR_HLm();
void XOR_lit(byte value);
//Or
void OR_reg(byte reg);
void OR_HLm();
void OR_lit(byte value);
//Compare
void CP_reg(byte reg);
void CP_HLm();
void CP_lit(byte value);

/////////////////
//Calls/Returns//
/////////////////
//Calls
void CALL_nn(word adr);
void CALLZ_nn(word adr);
void CALLNZ_nn(word adr);
void CALLC_nn(word adr);
void CALLNC_nn(word adr);
//Returns
void RET();
void RETZ();
void RETNZ();
void RETC();
void RETNC();
void RETI();
//Interrupt subroutine calls
void RST0();
void RST8();
void RST10();
void RST18();
void RST20();
void RST28();
void RST30();
void RST38();

//Pop & push
void POP_BC();
void POP_DE();
void POP_HL();
void POP_AF();

void PUSH_BC();
void PUSH_DE();
void PUSH_HL();
void PUSH_AF();

///////////////
//Other Stuff//
///////////////

void nop();
void stop();
void halt();
void IE();
void ID();

//TODO: 16-bit operations (0xCB)

#endif
